package com.zz.tijian.handle.ratelimiter.valve.impl;

import com.google.common.util.concurrent.RateLimiter;
import com.zz.tijian.handle.ratelimiter.annotation.DoRateLimiter;
import com.zz.tijian.handle.ratelimiter.res.RateLimiterResponseStrategy;
import com.zz.tijian.handle.ratelimiter.valve.IValveService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Slf4j
public class RateLimiterValve implements IValveService {

    //使用线程安全的map
     private static final ConcurrentMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();

    @Override
    public Object access(ProceedingJoinPoint jp, Method method, DoRateLimiter doRateLimiter, Object[] args) throws Throwable {
        //限流不做限制
        if (0 == doRateLimiter.permitsPerSecond()) {
            return jp.proceed();
        }
        //定义key
        String clazzName = jp.getTarget().getClass().getName();
        String methodName = method.getName();
        String key = clazzName + "." + methodName;

        // 单例模式双重检测机制
        RateLimiter rateLimiter = rateLimiterMap.get(key);
        if (rateLimiter == null) {
            synchronized (rateLimiterMap) {
                rateLimiter = rateLimiterMap.get(key);
                if (rateLimiter == null) {
                    rateLimiter = RateLimiter.create(doRateLimiter.permitsPerSecond());
                    rateLimiterMap.put(key, rateLimiter);
                }
            }
        }

        if (rateLimiter.tryAcquire()) {
            log.info("获取到令牌");
            return jp.proceed();
        }

        RateLimiterResponseStrategy strategy = doRateLimiter.responseStrategy().getDeclaredConstructor().newInstance();
        return strategy.getResponse(method);
    }
}
